package com.gavin.security;

import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class AES {

	private Cipher cipherEncode = null;
	private Cipher cipherDecode = null;

	public AES() {
	}

	public void init(String strKey, String strIV) {
		if (strKey.length() < 16) {
			throw new RuntimeException("Key length must be at least 16");
		}
		if (strIV.length() < 16) {
			throw new RuntimeException("IV length must be at least 16");
		}

		try {
			strKey = strKey.substring(0, 16);
			strIV = strIV.substring(0, 16);

			byte[] keyBytes = strKey.getBytes("utf-8");
			Security.addProvider(new BouncyCastleProvider());
			SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
			byte[] bysIV = strKey.getBytes("utf-8");
			IvParameterSpec iv = new IvParameterSpec(bysIV);

			this.cipherEncode = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			this.cipherEncode.init(Cipher.ENCRYPT_MODE, key, iv);
			this.cipherDecode = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			this.cipherDecode.init(Cipher.DECRYPT_MODE, key, iv);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public byte[] encode(byte[] bysContent) {
		if (this.cipherEncode == null) {
			return bysContent;
		}

		try {
			byte[] bysResult = null;
			synchronized (this.cipherEncode) {
				bysResult = this.cipherEncode.doFinal(bysContent);
			}

			return bysResult;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public String encode(String strText) {
		if (this.cipherEncode == null) {
			return strText;
		}

		try {
			byte[] byteContent = strText.getBytes("utf-8");
			byte[] bysResult = null;
			synchronized (this.cipherEncode) {
				bysResult = this.cipherEncode.doFinal(byteContent);
			}

			String strResult = Base64.encode(bysResult);
			return strResult;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public byte[] decode(byte[] bysEncoded) {
		if (this.cipherEncode == null) {
			return bysEncoded;
		}

		try {
			byte[] bysResult = null;
			synchronized (this.cipherDecode) {
				bysResult = this.cipherDecode.doFinal(bysEncoded);
			}

			return bysResult;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	};

	public String decode(String strEncoded) {
		if (this.cipherEncode == null) {
			return strEncoded;
		}

		byte[] bysEncoded = Base64.decode(strEncoded);

		try {
			byte[] bysResult = null;
			synchronized (this.cipherDecode) {
				bysResult = this.cipherDecode.doFinal(bysEncoded);
			}

			String strResult = new String(bysResult, "utf-8");
			return strResult;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	};

//	public static void main(String[] args) {
//
//		String strText = "张三";
//
//		AES test = new AES();
//		test.init("1234567890abcdef", "1234567890abcdef");
//
//		String strEncoded = null;
//		String strDecoded = null;
//		long lStartTime = System.currentTimeMillis();
//		for (int i = 0; i < 1; i++) {
//			strEncoded = test.encode(strText.toString());
//		}
//		long lDelay = System.currentTimeMillis() - lStartTime;
//		System.out.println(strEncoded);
//		System.out.println("Delay: " + lDelay);
//
//		// strEncoded="XKicls2yrqoaBc2gRZkLjL/fv1Cbh7ZzMAppFjG5FN1vNpmH19u2gA4sO+bsmYaDDS6MlU9DizxhTCVv/byst1zOsNjc7ab2IWY/rEVQ34p67pmI2w8cvhGb/ZVe38Po84soJm1W1izWJBsGYR/7n9Bd3JdIY0RqzFMBS9GqzVcFFz8fX4bZTTNeTxG8fO5FYo+DTpc/pR1ghhpJg6wSH2o1CEX9rIY+48GBEM6VzeytWm2juB5H68X6I2/aG6aAiFkDZQIMSUpFZr41CASg0P3Fy7dD3KH696GvAdhSDPLnTJxf02p6DFpo0KlOq3y3HJ6h1FEzIiJCh3Nwx1HGTDuEGxYRCwcoj7eHKWHK2fLUduzsvca6e/txgzLW1QHi";
//		lStartTime = System.currentTimeMillis();
//		for (int i = 0; i < 1; i++) {
//			strDecoded = test.decode(strEncoded);
//		}
//		lDelay = System.currentTimeMillis() - lStartTime;
//
//		System.out.println("Delay: " + lDelay);
//	}

}
